﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace Core.Utility.Helper
{
    /// <summary>
    /// XML助手类
    /// </summary>
    public static class XmlHelper
    {
        /// <summary>
        /// 格式化Xml
        /// </summary>
        /// <param name="xmlString"></param>
        /// <returns></returns>
        public static string FormatXml(string xmlString)
        {
            //校验是否是XML报文
            if (!xmlString.Contains("<?xml version")) return xmlString;
            try
            {
                XmlDocument xmlDocument = GetXmlDocument(xmlString);
                return ConvertXmlDocumentToString(xmlDocument);
            }
            catch
            {
                return xmlString;
            }
        }
        
        /// <summary>
        /// 转换XML文档为字符串
        /// </summary>
        /// <param name="xmlDocument"></param>
        /// <returns></returns>
        public static string ConvertXmlDocumentToString(XmlDocument xmlDocument)
        {
            string xmlString = xmlDocument.OuterXml;
            try
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (XmlTextWriter writer = new XmlTextWriter(memoryStream, null)) 
                    {
                        writer.Formatting = Formatting.Indented;//缩进
                        xmlDocument.Save(writer);
                        using (StreamReader streamReader = new StreamReader(memoryStream))
                        {
                            memoryStream.Position = 0;
                            xmlString = streamReader.ReadToEnd();
                            streamReader.Close();
                            writer.Close();
                            memoryStream.Close();
                        }
                    }
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine($"Xml格式化失败，{ex.Message}");
            }
            return xmlString;
        }

        /// <summary>
        /// 获取XmlDocument
        /// </summary>
        /// <param name="xmlString"></param>
        /// <returns></returns>
        public static XmlDocument GetXmlDocument(string xmlString)
        {
            XmlDocument document = new XmlDocument();
            document.LoadXml(xmlString);
            return document;
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xml"></param>
        /// <param name="xmlRootName"></param>
        /// <returns></returns>
        public static T? Deserialize<T>(string xml, string xmlRootName = "program")
        {
            T? result = default(T);
            using (StringReader sr = new StringReader(xml))
            {
                XmlSerializer xmlSerializer = string.IsNullOrWhiteSpace(xmlRootName) ?
                    new XmlSerializer(typeof(T)) : new XmlSerializer(typeof(T), new XmlRootAttribute(xmlRootName));
                result = (T?)xmlSerializer.Deserialize(sr);
            }
            return result;
        }

        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="sourceObj"></param>
        /// <param name="xmlRootName"></param>
        /// <returns></returns>
        public static string Serializer(object sourceObj, string xmlRootName = "program")
        {
            string str = string.Empty;
            using (MemoryStream Stream = new MemoryStream())
            {
                Type type = sourceObj.GetType();
                XmlSerializer xmlSerializer = string.IsNullOrWhiteSpace(xmlRootName) ?
                    new XmlSerializer(type) : new XmlSerializer(type, new XmlRootAttribute(xmlRootName));

                xmlSerializer.Serialize(Stream, sourceObj);
                Stream.Position = 0;
                StreamReader sr = new StreamReader(Stream);
                str = sr.ReadToEnd();
                sr.Dispose();
                Stream.Dispose();
            }
            return str;

        }
    }
}
